home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 5 / PIXELWOR / CPIXELWO.C1 < prev    next >
Text File  |  1992-01-01  |  27KB  |  938 lines

  1. /******************************************************************************
  2.  CPixelWorld.c
  3.  
  4.     Pixel World Class, Version 1.0                        (SUPERCLASS = CBitMap)
  5.     __________________________________________________________________________
  6.     
  7.     Ñ    Description
  8.         
  9.         The CPixelWorld class is a subclass of CBitMap (THINK Class Library 1.1) 
  10.         designed to maintain a color offscreen drawing environment using the 
  11.         standard conventions of Color QuickDraw.  An offscreen color graphics 
  12.         device (GDevice) and an offscreen color graphics port (CGrafPort) are 
  13.         used to maintain this offscreen world.  This implementation supports 
  14.         standard pixel depths of 1,2,4 and 8 bits.  Pixel depths of 16 and 32 
  15.         are not supported since this implementation does not rely on 32-Bit 
  16.         QuickDraw features.  In the future, support for 16 and 32 bit pixel 
  17.         depths and the offscreen GWorlds provided by 32-Bit QuickDraw can be 
  18.         incorporated into a subclass of CPixelWorld called CGWorld.  
  19.         
  20.     Ñ    Creating a Blank Pixel World
  21.         
  22.         A blank pixel world is created by calling the initialization method 
  23.         IPixelWorld() with a pixel depth (aPixelDepth), a bounds rectangle 
  24.         (aBoundsRect), a handle to a color table (aColorTable), and NULL for 
  25.         the handle to the pixel image (aPixelImage).  You can pass any value 
  26.         for row bytes (aRowBytes) since the value will be ignored in this case.  
  27.         You should pass a color table handle (CTabHandle) in the aColorTable 
  28.         parameter.  The color table is copied and the copy is used for the 
  29.         offscreen world.  If aColorTable is NULL, then the default color table 
  30.         for the desired pixel depth will be used.  
  31.         
  32.                                 *** WARNING ***
  33.         
  34.         If you request a pixel depth of one and Color QuickDraw is not 
  35.         available, then a blank offscreen world will be created as a standard 
  36.         BitMap with a non-color graphics port (GrafPort) using the CBitMap 
  37.         superclass.  If you request a pixel depth greater than one and Color 
  38.         QuickDraw is not available, the initialization method will fail.  To 
  39.         detect initialization failure call the method WorldIsOK(), which 
  40.         returns the value of the instance variable worldIsOK.  WorldIsOK() 
  41.         will return TRUE after successful initialization, and FALSE after 
  42.         initialization failure.  
  43.         
  44.     Ñ    Creating a Pixel World with an Existing Image
  45.         
  46.         A world based on an existing color or grayscale image is created by 
  47.         calling the initialization method IPixelWorld() with the pixel depth of 
  48.         the existing image (aPixelDepth), the bounds rectangle of the existing 
  49.         image (aBoundsRect), a color table for the existing image (aColorTable), 
  50.         and a handle to the pixels for the existing image (aPixelImage).  In 
  51.         this case, you must also pass a value for the row bytes of the pixel 
  52.         image (aRowBytes).  
  53.         
  54.                                *** IMPORTANT ***
  55.         
  56.         When you create an offscreen world based on an existing pixel image, 
  57.         IT IS YOUR RESPONSIBILITY TO DISPOSE OF YOUR PIXEL IMAGE.  Although 
  58.         CPixelWorld keeps its own handle to your pixel image in the instance 
  59.         variable worldPixels, it will not dispose of the pixel image.  In 
  60.         contrast, when you create a blank world by passing NULL for the 
  61.         aPixelImage parameter, CPixelWorld creates its own pixel image and it 
  62.         will dispose of this image when the offscreen world is destroyed by 
  63.         the Dispose() instance method.  
  64.         
  65.         When you create your own pixel image for use with an offscreen world 
  66.         use a multiple of four for the row bytes of your pixel image.  The 
  67.         following formula will give a multiple of four for row bytes:  
  68.         
  69.             rowBytes = ((((long) width * pixelDepth) + 31) / 32) * 4;
  70.         
  71.         A multiple of four for row bytes will give optimal performance in calls 
  72.         to the QuickDraw function CopyBits() and its related functions.  
  73.         
  74.                                 *** WARNING ***
  75.         
  76.         When you create an offscreen world with an existing image that has a 
  77.         pixel depth greater than one, the initialization method will fail if 
  78.         Color QuickDraw is not available since there is no support for images 
  79.         with pixel depths greater than one without Color QuickDraw.  
  80.         
  81.     Ñ    Drawing to the Offscreen Pixel World
  82.         
  83.         If you need to draw directly to the offscreen world, you must bracket
  84.         all drawing with calls to BeginDrawing() and EndDrawing().  This will 
  85.         set up the offscreen GDevice and CGrafPort for drawing.  In addition, 
  86.         the LockWorld() method will be called to make sure that the pixel 
  87.         image is anchored down and will not move when you invoke any QuickDraw
  88.         routines.  LockWorld() locks the handle to the pixel image, and then 
  89.         it loads the derefernced handle into the PixMap baseAddr pointers of 
  90.         both the offscreen GDevice and the offscreen CGrafPort.  
  91.         
  92.     Ñ    Version History
  93.         
  94.         __________________________________________________________
  95.         Release Version:        1.0
  96.         Release Date:            January 1, 1992
  97.         
  98.         Implemented By:            Vincent R. Vann, Jr.
  99.                                 1901 Brickell Ave, B-410
  100.                                 Miami, Florida  33129  USA
  101.         
  102.         Compuserve Address:     76530,1242
  103.         Internet Address:        vvann@umbio.med.miami.edu
  104.                                 (129.171.65.204)
  105.         __________________________________________________________
  106.         
  107.     Ñ    License Agreement
  108.         
  109.         All portions of this source code are property of Vincent R. Vann, Jr.
  110.         I, Vincent R. Vann, Jr., grant you the right to freely distribute this 
  111.         source code and to use all or part of this source code in all software  
  112.         including commercial, freeware, shareware and private applications.  
  113.         However, all software that uses any part of or all of this source code 
  114.         must display a copyright notice indicating that either all of or 
  115.         portions of this source code are used in the software.  I also grant 
  116.         you permission to alter and make improvements to this source code, but 
  117.         only if all modifications are returned to me by whatever means are 
  118.         available, either in written or electronic form.  You must also accept 
  119.         that I retain the right to include any part of your modifications or 
  120.         all of your modifications in future releases of this source code.  The 
  121.         description and version history sections above may be ammended for 
  122.         documentation purposes.  This license agreement and the copyright 
  123.         notice below must be maintained intact and must be included with all 
  124.         distributions of this source code at all times.  
  125.         
  126.         This implementation is based in part on material copyrighted by Apple 
  127.         Computer, Inc. and Symantec Corporation.  
  128.         
  129.         Copyright ⌐ 1992 Vincent R. Vann, Jr.  All rights reserved.  
  130.         
  131.  ******************************************************************************/
  132.  
  133.  
  134. #include "CPixelWorld.h"
  135. #include "CDesktop.h"
  136. #include "Exceptions.h"
  137. #include "Global.h"
  138. #include "LongQD.h"
  139. #include "TCLUtilities.h"
  140.  
  141.  
  142. /**** C O N S T R U C T I O N / D E S T R U C T I O N   M E T H O D S ****/
  143.  
  144.  
  145. /******************************************************************************
  146.  IPixelWorld
  147.  
  148.         Initialize a PixelWorld object
  149.  ******************************************************************************/
  150.  
  151. void    CPixelWorld::IPixelWorld(
  152.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  153.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  154.     CTabHandle    aColorTable,        /* ColorTable for world    image        */
  155.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  156.     short        aRowBytes)            /* Row bytes of pixel image            */
  157. {
  158.         /* Initialize instance variables of CBitMap superclass */
  159.     
  160.     macPort = NULL;
  161.     savePort = NULL;
  162.     macBitMap = NULL;
  163.     xferMode = srcCopy;
  164.     
  165.         /* Initialize instance variables of CPixelWorld class */
  166.     
  167.     worldIsOK = FALSE;                    /* TRUE if initialized successfully    */
  168.     worldHasColor = gSystem.hasColorQD;    /* TRUE if have Color QuickDraw        */
  169.     worldHas32BitQD = FALSE;            /* TRUE if have 32-Bit QuickDraw    */
  170.     worldOwnsPixels = FALSE;            /* TRUE if world owns pixel image    */
  171.     worldPixelsLocked = FALSE;            /* TRUE if pixel image is locked    */
  172.     
  173.     worldDepth = 0;
  174.     
  175.     worldBounds.left = 0;
  176.     worldBounds.top = 0;
  177.     worldBounds.right = 0;
  178.     worldBounds.bottom = 0;
  179.     
  180.     worldColors = NULL;
  181.     worldDevice = NULL;
  182.     worldPort = NULL;
  183.     worldPixels = NULL;
  184.     
  185.     saveDevice = NULL;
  186.     
  187.     if (!worldHasColor)
  188.         IPixelWorldBW( aPixelDepth, aBoundsRect, aPixelImage, aRowBytes);
  189.     else
  190.         IPixelWorldColor( aPixelDepth, aBoundsRect, aColorTable, aPixelImage, aRowBytes);
  191. }
  192.  
  193.  
  194. /******************************************************************************
  195.  IPixelWorldBW
  196.  
  197.         Initialize a black and white pixel world
  198.  ******************************************************************************/
  199.  
  200. void    CPixelWorld::IPixelWorldBW(
  201.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  202.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  203.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  204.     short        aRowBytes)            /* Row bytes of pixel image            */
  205. {
  206.     GrafPtr        theSavedPort;
  207.     Boolean        theSavedAlloc;
  208.     short        rowBytes;
  209.     long        bytes, width, height;
  210.     
  211.     /***
  212.      *** Check for a valid pixel depth
  213.      ***/
  214.     
  215.     if (aPixelDepth != 1) return;
  216.     
  217.     /***
  218.      *** Create the offscreen bitmap
  219.      ***/
  220.     
  221.     width = aBoundsRect->right - aBoundsRect->left;
  222.     height = aBoundsRect->bottom - aBoundsRect->top;
  223.     
  224.     if (aPixelImage != NULL && aRowBytes != 0)
  225.         rowBytes = aRowBytes;
  226.     else
  227.         rowBytes = ((width * aPixelDepth + 31) / 32 ) * 4;
  228.     
  229.     bytes = height * rowBytes;
  230.     
  231.     theSavedAlloc = SetAllocation( kAllocCanFail);
  232.     macBitMap = (BitMap *) NewPtrClear(sizeof(BitMap) + bytes);
  233.     SetAllocation( theSavedAlloc);
  234.     
  235.     FailNIL( macBitMap);
  236.     
  237.     macBitMap->baseAddr = (Ptr) (macBitMap + 1);
  238.     macBitMap->rowBytes = rowBytes;
  239.     macBitMap->bounds = *aBoundsRect;
  240.     
  241.     /***
  242.      *** Copy the existing pixel image into the offscreen bitmap
  243.      ***/
  244.     
  245.     if (aPixelImage != NULL && aRowBytes != 0)
  246.     {
  247.         long    n;
  248.         
  249.         n = GetHandleSize(aPixelImage);
  250.         if (n > 0 && MemError() == noErr)
  251.         {
  252.             if (n > bytes) n = bytes;
  253.             
  254.             HLock( aPixelImage);
  255.             BlockMove( (Ptr) *aPixelImage, macBitMap->baseAddr, n);
  256.             HUnlock( aPixelImage);
  257.         }
  258.     }
  259.     
  260.     /***
  261.      *** Create the offscreen graphics port 
  262.      ***/
  263.     
  264.     theSavedAlloc = SetAllocation( kAllocCanFail);
  265.     macPort = (GrafPtr) NewPtrClear( sizeof(GrafPort));
  266.     SetAllocation( theSavedAlloc);
  267.     
  268.     FailNIL( macPort);
  269.     
  270.     GetPort( &theSavedPort);
  271.     
  272.         OpenPort( macPort);
  273.         SetPort( macPort);
  274.         
  275.         SetPortBits( macBitMap);
  276.         macPort->portRect = *aBoundsRect;
  277.         RectRgn( macPort->visRgn, aBoundsRect);
  278.         RectRgn( macPort->clipRgn, aBoundsRect);
  279.         
  280.     SetPort( theSavedPort);
  281.     
  282.     CView::ForceNextPrepare();
  283.     
  284.     worldIsOK = TRUE;
  285. }
  286.  
  287.  
  288. /******************************************************************************
  289.  IPixelWorldColor
  290.  
  291.         Initialize a color pixel world
  292.  ******************************************************************************/
  293.  
  294. void    CPixelWorld::IPixelWorldColor(
  295.     short        aPixelDepth,        /* Pixel depth of world in bits        */
  296.     Rect        *aBoundsRect,        /* Bounds rectangle of world        */
  297.     CTabHandle    aColorTable,        /* ColorTable for world    image        */
  298.     Handle        aPixelImage,        /* Handle to pixel image for world    */
  299.     short        aRowBytes)            /* Row bytes of pixel image            */
  300. {
  301.     GDHandle    theSavedDevice;
  302.     GrafPtr        theSavedPort;
  303.     Boolean        theSavedAlloc;
  304.     
  305.     /***
  306.      *** Check for a valid pixel depth
  307.      ***/
  308.     
  309.     if (aPixelDepth != 1 && aPixelDepth != 2 && aPixelDepth != 4 && aPixelDepth != 8)
  310.         return;
  311.     
  312.     /***
  313.      *** Set worldDepth and worldBounds instance variables
  314.      ***/
  315.     
  316.     worldDepth = aPixelDepth;
  317.     
  318.     worldBounds.left = aBoundsRect->left;
  319.     worldBounds.top = aBoundsRect->top;
  320.     worldBounds.right = aBoundsRect->right;
  321.     worldBounds.bottom = aBoundsRect->bottom;
  322.     
  323.     /***
  324.      *** Create the world color table
  325.      ***/
  326.     
  327.     if (aColorTable != NULL)        /* Copy the color table */
  328.     {
  329.         OSErr    error;
  330.         
  331.         theSavedAlloc = SetAllocation( kAllocCanFail);
  332.         error = HandToHand( &aColorTable);
  333.         SetAllocation( theSavedAlloc);
  334.         
  335.         FailOSErr(error);
  336.         
  337.         worldColors = aColorTable;
  338.     }
  339.     else                            /* Use standard color table for the pixel depth */
  340.     {
  341.         worldColors = GetCTable( aPixelDepth);
  342.     }
  343.     
  344.     /***
  345.      *** Create the world pixel image 
  346.      ***/
  347.     
  348.     if (aPixelImage != NULL && aRowBytes != 0)        /* Use the existing pixel image */
  349.     {
  350.         HUnlock( aPixelImage);
  351.         
  352.         worldPixels = aPixelImage;
  353.         worldOwnsPixels = FALSE;    /* We don't own the pixel image */
  354.     }
  355.     else                                            /* Create a new blank pixel image */
  356.     {
  357.         long    width, height;
  358.         
  359.         width = aBoundsRect->right - aBoundsRect->left;
  360.         height = aBoundsRect->bottom - aBoundsRect->top;
  361.         
  362.         aRowBytes = ((width * aPixelDepth + 31) / 32 ) * 4;
  363.         
  364.         theSavedAlloc = SetAllocation( kAllocCanFail);
  365.         aPixelImage = NewHandleClear( height * aRowBytes);
  366.         SetAllocation( theSavedAlloc);
  367.         
  368.         FailNIL( aPixelImage);
  369.         
  370.         worldPixels = aPixelImage;
  371.         worldOwnsPixels = TRUE;        /* We own the pixel image, and must dispose of it */
  372.     }
  373.     
  374.     /***
  375.      *** Create the offscreen graphics device 
  376.      ***/
  377.     
  378.     worldDevice = NewGDevice( 0, -1L);
  379.     FailNIL( worldDevice);
  380.     
  381.     HLock(worldDevice);
  382.     {
  383.         GDPtr    gdev = *worldDevice;
  384.         
  385.         gdev->gdID = 0;
  386.         gdev->gdType = clutType;
  387.         gdev->gdResPref = 4;
  388.         gdev->gdSearchProc = NULL;
  389.         gdev->gdCompProc = NULL;
  390.         gdev->gdFlags = (1<<gdDevType) | (1<<ramInit) | (1<<noDriver) | (1<<screenActive);
  391.         gdev->gdRect = *aBoundsRect;
  392.         
  393.         HLock(gdev->gdPMap);
  394.         {
  395.             PixMapPtr    pmap = *gdev->gdPMap;
  396.             
  397.             pmap->baseAddr = NULL;
  398.             pmap->rowBytes = aRowBytes | 0x8000;
  399.             pmap->bounds = *aBoundsRect;
  400.             pmap->pixelSize = aPixelDepth;
  401.             pmap->cmpCount = 1;
  402.             pmap->cmpSize = aPixelDepth;
  403.             
  404.             DisposCTable(pmap->pmTable);
  405.             pmap->pmTable = worldColors;
  406.         }
  407.         HUnlock(gdev->gdPMap);
  408.     }
  409.     HUnlock(worldDevice);
  410.     
  411.     MakeITable( worldColors, (**worldDevice).gdITable, 4);
  412.     FailOSErr( QDError());
  413.     
  414.     /***
  415.      *** Create the offscreen graphics port 
  416.      ***/
  417.     
  418.     theSavedAlloc = SetAllocation( kAllocCanFail);
  419.     worldPort = (CGrafPtr) NewPtrClear( sizeof(CGrafPort));
  420.     SetAllocation( theSavedAlloc);
  421.     
  422.     FailNIL( worldPort);
  423.     
  424.     theSavedDevice = GetGDevice();
  425.     GetPort( &theSavedPort);
  426.     
  427.         SetGDevice( worldDevice);
  428.         OpenCPort( worldPort);
  429.         
  430.         worldPort->portRect = *aBoundsRect;
  431.         RectRgn( worldPort->visRgn, aBoundsRect);
  432.         RectRgn( worldPort->clipRgn, aBoundsRect);
  433.         
  434.     SetGDevice( theSavedDevice);
  435.     SetPort( theSavedPort);
  436.     
  437.     CView::ForceNextPrepare();
  438.     
  439.     worldIsOK = TRUE;
  440. }
  441.  
  442.  
  443. /******************************************************************************
  444.  Dispose {OVERRIDE}
  445.  
  446.         Dispose of a PixelWorld
  447.  ******************************************************************************/
  448.  
  449. void    CPixelWorld::Dispose()
  450. {
  451.     if (worldPort != NULL)
  452.     {
  453.         ClosePort( worldPort);            /* Close the color graphics port */
  454.         DisposPtr( worldPort);            /* Dispose of color graphics port */
  455.     }
  456.     
  457.     if (worldDevice != NULL)
  458.     {
  459.         DisposGDevice( worldDevice);    /* Dispose of gDevice and colorTable */
  460.     }
  461.     else
  462.     {
  463.         DisposCTable( worldColors);        /* Dispose of the colorTable */
  464.     }
  465.     
  466.     if (worldPixels != NULL && worldOwnsPixels)
  467.     {
  468.         DisposHandle( worldPixels);        /* Dispose of pixel image */
  469.     }
  470.     
  471.         /* The inherited method disposes of black & white pixel worlds */
  472.     
  473.     inherited::Dispose();
  474. }
  475.  
  476.  
  477. /******************************************************************************
  478.  WorldIsOK
  479.  
  480.         Return TRUE if world has been initialized successfully, FALSE otherwise.
  481.  ******************************************************************************/
  482.  
  483. Boolean        CPixelWorld::WorldIsOK()
  484. {
  485.     return( worldIsOK);
  486. }
  487.  
  488.  
  489. /******************************************************************************
  490.  GetBounds {OVERRIDE}
  491.  
  492.         Return the bounding rectangle of a PixelWorld. This rectangle defines
  493.         the size and coordinate system of the PixelWorld.
  494.  ******************************************************************************/
  495.  
  496. void    CPixelWorld::GetBounds(
  497.     LongRect        *theBounds)
  498. {
  499.     *theBounds = worldBounds;
  500. }
  501.  
  502.  
  503. /******************************************************************************
  504.  SetBoundsOrigin {OVERRIDE}
  505.  
  506.         Set the coordinates of the top left corner of the bounds of a
  507.         PixelWorld. This changes the coordinate system of the PixelWorld.
  508.         Note that the visRgn and clipRgn of the PixelWorld are reset.
  509.  ******************************************************************************/
  510.  
  511. void    CPixelWorld::SetBoundsOrigin(
  512.     short        hOrigin,
  513.     short        vOrigin)
  514. {
  515.     Rect        bounds;
  516.     
  517.     if (!worldIsOK) return;
  518.     
  519.     bounds.left = hOrigin;
  520.     bounds.top = vOrigin;
  521.     bounds.right = hOrigin + (worldBounds.right - worldBounds.left);
  522.     bounds.bottom = vOrigin + (worldBounds.bottom - worldBounds.top);
  523.     
  524.     worldBounds.left = bounds.left;
  525.     worldBounds.top = bounds.top;
  526.     worldBounds.right = bounds.right;
  527.     worldBounds.bottom = bounds.bottom;
  528.     
  529.     if (worldHasColor)            /* World has color */
  530.     {
  531.         HLock(worldDevice);
  532.         {
  533.             GDPtr    gdev = *worldDevice;
  534.             
  535.             (**gdev->gdPMap).bounds = bounds;
  536.             gdev->gdRect = bounds;
  537.         }
  538.         HUnlock(worldDevice);
  539.         
  540.         (**worldPort->portPixMap).bounds = bounds;
  541.         worldPort->portRect = bounds;
  542.         RectRgn( worldPort->visRgn, &bounds);
  543.         RectRgn( worldPort->clipRgn, &bounds);
  544.     }
  545.     else                        /* World is black and white */
  546.     {
  547.         macBitMap->bounds = bounds;
  548.         macPort->portBits.bounds = bounds;
  549.         macPort->portRect = bounds;
  550.         
  551.         RectRgn( macPort->visRgn, &bounds);
  552.         RectRgn( macPort->clipRgn, &bounds);
  553.     }
  554. }
  555.  
  556.  
  557. /******************************************************************************
  558.  PixelIsBlack {OVERRIDE}
  559.  
  560.         Determine whether the pixel at the specified coordinates is black.
  561.         Returns FALSE if the pixel is not black or it is not within the
  562.         world bounds rectangle.
  563.  ******************************************************************************/
  564.  
  565. Boolean        CPixelWorld::PixelIsBlack(
  566.     LongPt        *pixelPos)
  567. {
  568.     RGBColor    color;
  569.     
  570.     if (!worldIsOK) return (FALSE);
  571.     
  572.     if (worldHasColor)        /* World has color */
  573.     {
  574.         if (GetPixelColor( pixelPos, &color) == TRUE)    /* Inside */
  575.         {
  576.             if (color.red == 0 && color.green == 0 && color.blue == 0)
  577.                 return (TRUE);
  578.             else
  579.                 return (FALSE);
  580.         }
  581.         else
  582.         {
  583.             return (TRUE);     /* Pixel is outside and must be black */
  584.         }
  585.     }
  586.     else                    /* World is black and white */
  587.     {
  588.         return (inherited::PixelIsBlack(pixelPos));
  589.     }
  590. }
  591.  
  592.  
  593. /******************************************************************************
  594.  GetPixelColor
  595.  
  596.         Determines the color of the pixel at the specified coordinates.
  597.         Returns FALSE if the point is not within the PixelWorld.
  598.         
  599.                             *** IMPORTANT ***
  600.         
  601.         The offscreen pixel world must be active and the worldPixels
  602.         must be locked for this method to work properly.  Therefore, 
  603.         always send a BeginDrawing message before calling GetPixelColor().
  604.         When you are finished getting all the pixel colors you need,
  605.         then send the EndDrawing message to restore the previous
  606.         drawing environment.  
  607.  ******************************************************************************/
  608.  
  609. Boolean        CPixelWorld::GetPixelColor(
  610.     LongPt        *pixelPos,
  611.     RGBColor    *color)
  612. {
  613.     LongRect    bounds = worldBounds;
  614.     
  615.     if (!worldIsOK) return (FALSE);
  616.     
  617.     if (!PtInLongRect( pixelPos, &bounds))    /* Pixel is OUTSIDE bounds rectangle */
  618.         return (FALSE);
  619.     
  620.     if (worldHasColor)        /* World has color */
  621.     {
  622.         if (worldPixelsLocked)
  623.             GetCPixel((short) pixelPos->h, (short) pixelPos->v, color);    /* Get color */
  624.         else
  625.             color->red = color->green = color->blue = 0;        /* Black */
  626.     }
  627.     else                    /* World is black and white */
  628.     {
  629.         if (inherited::PixelIsBlack(pixelPos))
  630.             color->red = color->green = color->blue = 0;        /* Black */
  631.         else
  632.             color->red = color->green = color->blue = 65535;    /* White */
  633.     }
  634.     
  635.     return(TRUE);                            /* Pixel is INSIDE bounds rectangle */
  636. }
  637.  
  638.  
  639. /******************************************************************************
  640.  GetPixelDepth
  641.  
  642.         Return the bounding rectangle of a PixelWorld. This rectangle defines
  643.         the size and coordinate system of the PixelWorld.
  644.  ******************************************************************************/
  645.  
  646. short    CPixelWorld::GetPixelDepth()
  647. {
  648.     return (worldDepth);
  649. }
  650.  
  651.  
  652. /******************************************************************************
  653.  GetRowBytes
  654.  
  655.         Return row byte length for the offscreen image.
  656.  ******************************************************************************/
  657.  
  658. short    CPixelWorld::GetRowBytes()
  659. {
  660.     short    rowBytes;
  661.     
  662.     if (!worldIsOK) return (0);
  663.     
  664.     if (worldHasColor)        /* World has color */
  665.     {
  666.         rowBytes = (**worldPort->portPixMap).rowBytes;
  667.     }
  668.     else                    /* World is black and white */
  669.     {
  670.         rowBytes = macBitMap->rowBytes;
  671.     }
  672.     
  673.     rowBytes &= 0x7FFF;
  674.     return (rowBytes);
  675. }
  676.  
  677.  
  678. /******************************************************************************
  679.  GetHandleToPixels
  680.  
  681.         Return a handle to the pixel image.  The handle is valid when the 
  682.         offscreen world is in color but not when its a black and white CBitMap 
  683.         world.  If the image is a black and white, this function returns NULL.  
  684.  ******************************************************************************/
  685.  
  686. Handle    CPixelWorld::GetHandleToPixels()
  687. {
  688.     return( worldPixels);
  689. }
  690.  
  691.  
  692. /******************************************************************************
  693.  GetPointerToPixels
  694.  
  695.         Return a pointer to the pixel image.  Works for color and black/white 
  696.         images as well.  
  697.  ******************************************************************************/
  698.  
  699. Ptr        CPixelWorld::GetPointerToPixels()
  700. {
  701.     if (!worldIsOK) return (NULL);
  702.     
  703.     if (worldHasColor)        /* World has color */
  704.     {
  705.         return( (Ptr) *worldPixels);
  706.     }
  707.     else                    /* World is black and white */
  708.     {
  709.         return( (Ptr) macBitMap->baseAddr);
  710.     }
  711. }
  712.  
  713.  
  714. /******************************************************************************
  715.  LockWorld
  716.  
  717.         Lock or unlock the worldPixels handle according to the setLock flag.
  718.         If setLock is true, then the worldPixels handle is locked and the 
  719.         de-referenced handle is put into the baseAddr field of worldDevice 
  720.         and worldPort PixMap structures.  
  721.  ******************************************************************************/
  722.  
  723. Boolean        CPixelWorld::LockWorld(
  724.     Boolean        setLock)
  725. {
  726.     if (!worldIsOK) return (FALSE);
  727.  
  728.     if (worldHasColor)
  729.     {
  730.         if (worldPixelsLocked)
  731.         {
  732.             if (!setLock)
  733.             {
  734.                 PixMapHandle    hMap;
  735.                 
  736.                 HUnlock(worldPixels);
  737.                 
  738.                 hMap = (**worldDevice).gdPMap;
  739.                 (**hMap).baseAddr = NULL;
  740.                 
  741.                 hMap = worldPort->portPixMap;
  742.                 (**hMap).baseAddr = NULL;
  743.                 
  744.                 worldPixelsLocked = FALSE;
  745.             }
  746.             
  747.             return (TRUE);
  748.         }
  749.         else
  750.         {
  751.             if (setLock)
  752.             {
  753.                 PixMapHandle    hMap;
  754.                 
  755.                 MoveHHi(worldPixels);
  756.                 HLock(worldPixels);
  757.                 
  758.                 hMap = (**worldDevice).gdPMap;
  759.                 (**hMap).baseAddr = (Ptr) *worldPixels;
  760.                 
  761.                 hMap = worldPort->portPixMap;
  762.                 (**hMap).baseAddr = (Ptr) *worldPixels;
  763.                 
  764.                 worldPixelsLocked = TRUE;
  765.             }
  766.             
  767.             return (FALSE);
  768.         }
  769.     }
  770.     
  771.     return (FALSE);
  772. }
  773.  
  774.  
  775. /******************************************************************************
  776.  ActivateWorld
  777.  
  778.         Activates the offscreen pixel world so that all drawing will take
  779.         place in the offscreen graphics port.  The currently active graphics 
  780.         device and port are saved so they can be restored later.  
  781.  ******************************************************************************/
  782.  
  783. void    CPixelWorld::ActivateWorld()
  784. {
  785.     if (!worldIsOK) return;
  786.     
  787.     if (worldHasColor)            /* World has color */
  788.     {
  789.         saveDevice = GetGDevice();
  790.         GetPort( &savePort);
  791.         
  792.         LockWorld( TRUE);
  793.         
  794.         SetGDevice( worldDevice);
  795.         SetPort( worldPort);
  796.     }
  797.     else                        /* World is black and white */
  798.     {
  799.         GetPort( &savePort);
  800.         SetPort( macPort);
  801.     }
  802. }
  803.  
  804.  
  805. /******************************************************************************
  806. DeactivateWorld
  807.  
  808.         Restores the previously active graphics device and port.
  809.  ******************************************************************************/
  810.  
  811. void    CPixelWorld::DeactivateWorld()
  812. {
  813.     if (!worldIsOK) return;
  814.     
  815.     if (worldHasColor)            /* World has color */
  816.     {
  817.         LockWorld( FALSE);
  818.         
  819.         if (saveDevice != NULL) SetGDevice( saveDevice);
  820.         if (savePort != NULL) SetPort( savePort);
  821.         
  822.         saveDevice = NULL;
  823.         savePort = NULL;
  824.     }
  825.     else
  826.     {
  827.         if (savePort != NULL) SetPort( savePort);
  828.         savePort = NULL;
  829.     }
  830. }
  831.  
  832.  
  833. /******************************************************************************
  834.  CopyTo {OVERRIDE}
  835.  
  836.         Copy bits to a PixelWorld from the bit map of the current port. The
  837.         fromRect is a rectangle in the current port's bit map (source rect),
  838.         and the toRect is a rectangle in this PixelWorld (dest rect). maskRgn is
  839.         a clipping region specified in the same coords as the dest rect,
  840.         i.e., the coords of this PixelWorld. A NULL maskRgn means that no extra
  841.         clipping is performed. Copying takes place using the transfer mode
  842.         stored in the xferMode instance variable.
  843.  ******************************************************************************/
  844.  
  845. void    CPixelWorld::CopyTo(
  846.     LongRect    *fromRect,
  847.     LongRect    *toRect,
  848.     RgnHandle    maskRgn)
  849. {
  850.     if (!worldIsOK) return;
  851.     
  852.     if (worldHasColor)            /* World has color */
  853.     {
  854.         Boolean        savedLock;
  855.         
  856.         savedLock = LockWorld( TRUE);
  857.         LCopyBits( &thePort->portBits, &((GrafPtr)worldPort)->portBits, 
  858.                     fromRect, toRect, xferMode, maskRgn);
  859.         LockWorld( savedLock);
  860.     }
  861.     else                        /* World is black and white */
  862.     {                                    /* Call the inherited method */
  863.         inherited::CopyTo( fromRect, toRect, maskRgn);
  864.     }
  865. }
  866.  
  867.  
  868. /******************************************************************************
  869.  CopyFrom {OVERRIDE}
  870.  
  871.         Copy bits from a PixelWorld to the bit map of the current port. The
  872.         fromRect is a rectangle in this PixelWorld (source rect), and the
  873.         toRect is a rectangle in the current port's bit map (dest rect).
  874.         maskRgn is a clipping region specified in the same coords as the
  875.         dest rect, i.e., the coords of the current port. A NULL maskRgn means
  876.         that no extra clipping is performed. Copying takes place using the
  877.         transfer mode stored in the xferMode instance variable.
  878.  ******************************************************************************/
  879.  
  880. void    CPixelWorld::CopyFrom(
  881.     LongRect    *fromRect,
  882.     LongRect    *toRect,
  883.     RgnHandle    maskRgn)
  884. {
  885.     if (!worldIsOK) return;
  886.     
  887.     if (worldHasColor)            /* World has color */
  888.     {
  889.         Boolean        savedLock;
  890.         
  891.         savedLock = LockWorld( TRUE);
  892.         LCopyBits( &((GrafPtr)worldPort)->portBits, &thePort->portBits, 
  893.                     fromRect, toRect, xferMode, maskRgn);
  894.         LockWorld( savedLock);
  895.     }
  896.     else                        /* World is black and white */
  897.     {                                    /* Call the inherited method */
  898.         inherited::CopyFrom( fromRect, toRect, maskRgn);
  899.     }
  900. }
  901.  
  902.  
  903. /******************************************************************************
  904.  BeginDrawing {OVERRIDE}
  905.  
  906.         Always end this message before performing any drawing to the 
  907.         offscreen pixel world. This function saves the current GDevice 
  908.         and GrafPort, activates the worldDevice and worldPort, and sends
  909.         a LockWorld(TRUE) message to lock down the pixel image.  
  910.         
  911.         If you do not call BeginDrawing() before drawing to the offscreen 
  912.         world, the PixMaps of the worldDevice and worldPort will have NULL 
  913.         baseAddr pointers and any drawing calls will probably cause a CRASH 
  914.         since low memory addresses will be overwritten !!!!!!  
  915.  ******************************************************************************/
  916.  
  917. void    CPixelWorld::BeginDrawing()
  918. {
  919.     ActivateWorld();
  920. }
  921.  
  922.  
  923. /******************************************************************************
  924.  EndDrawing {OVERRIDE}
  925.  
  926.         Always send this message after performing any drawing to the
  927.         offscreen pixel world.  This function resets the port to the 
  928.         way it was before the BeginDrawing message.  It restores the 
  929.         saved GDevice and GrafPort, and unlocks the pixel image.  
  930.  ******************************************************************************/
  931.  
  932. void    CPixelWorld::EndDrawing()
  933. {
  934.     DeactivateWorld();
  935. }
  936.  
  937.  
  938.